require.config({
	baseUrl : 'lib/zrender'
});

require(['zrender', 'shape/Rectangle', 'tool/event', 'animation/Animation'], function(zrender, Rectangle, eventTool){
	var zr = zrender.init(document.getElementById('main'));
	var listTile = null;
	var domScore = document.getElementById('score');
	var domRestart = document.getElementById('restart');
	var colors = [
		{color: '#f9f6f2', back: '#3c3a32'}, //super
		{color: '#776e65', back: '#eee4da'}, //2       1
		{color: '#776e65', back: '#ede0c8'}, //4       2
		{color: '#f9f6f2', back: '#f2b179'}, //8       3
		{color: '#f9f6f2', back: '#f59563'}, //16      4
		{color: '#f9f6f2', back: '#f67c5f'}, //32      5
		{color: '#f9f6f2', back: '#f65e3b'}, //64      6
		{color: '#f9f6f2', back: '#edcf72'}, //128     7
		{color: '#f9f6f2', back: '#edcc61'}, //256     8
		{color: '#f9f6f2', back: '#edc850'}, //512     9
		{color: '#f9f6f2', back: '#edc53f'}, //1024   10
		{color: '#f9f6f2', back: '#edc22e'}, //2048   11
	];	

	/* 生成背景格子 */
	function genGrid(){
		for(var row = 0; row < 4; row ++){
			for(var col = 0; col < 4; col ++){
				var x =col > 0 ? col * 106 + 15 * col : col * 106,
					y =row > 0 ? row * 106 + 15 * row : row * 106;

					zr.addShape(new Rectangle({
						style: {
							x: x,
							y: y,
							width: 106,
							height: 106,
							radius: 3,
							color: 'rgba(238, 228, 218, 0.35)',
						},
						hoverable: false,
					}));				
			}
		}
	}

	/* 生成方块 */
	function genTile(text, position){
		var fontSize, x, y;

		var x =position[1] > 0 ? position[1] * 106 + 15 * position[1] : position[1] * 106,
			y =position[0] > 0 ? position[0] * 106 + 15 * position[0] : position[0] * 106;

		if(+text >= 4096){
			fontSize = 30;
		}else if(+text >= 1024){
			fontSize = 35;
		}else if(+text >= 128){
			fontSize = 45;
		}else{
			fontSize = 55;
		}
		
		var tile = new Rectangle({
			style: {
				x: x,
				y: y,
				width: 106,
				height: 106,
				radius: 3,
				color: Math.log2(+text) >= 12 ? colors[0].back : colors[Math.log2(+text)].back,
				text: text,
				textColor: Math.log2(+text) >= 12 ? colors[0].back : colors[Math.log2(+text)].color,
				textPosition: 'inside',
				textFont: 'bold ' + fontSize + 'px Arial',
			},
			hoverable: false,
			zlevel: 1,
			cell:{
				row: position[0],
				col: position[1],	
			}			
		});
		
		zr.addShape(tile);
		return listTile[position[0]][position[1]] = tile;
		
	}

	/* 初始化格子存储列表 */
	function initListTile(){
		listTile = [];
		for(var x = 0; x < 4; x ++){
			listTile[x] = [];
			for(var y = 0; y < 4; y ++){
				listTile[x].push(null);
			}
		}
	}

	/* 添加随机方块 */
	function addRndTile(){
		if(!!getAvailableCells().length){
			var value = Math.random() > 0.3 ? 2 : 4;
			var cells = getAvailableCells();
			var pos = cells[Math.floor(Math.random() * cells.length)];
			genTile(value + '', [pos.x, pos.y]);			
		}
	}

	/* 生成开始方块 */
	function genStartTile(size){
		while(size --){
			addRndTile();
		}
	}

	/* 获取空格子 */
	function getAvailableCells(){
		var cells = [];

		for(var x = 0; x < 4; x ++){
			for(var y = 0; y < 4; y ++){
				if(!listTile[x][y]){
					cells.push({x : x, y : y});
				}
			}
		}

		return cells;
	}

	/* 是否能移动 */
	function isMoveAvailable(){
		//如果有可用格子，直接返回true
		if(!!getAvailableCells.length) return true;

		for(var x = 0; x < 4; x ++){
			for(var y = 0; y < 4; y ++){
				var tile = listTile[x][y];

				if(tile){
					for(var dir = 0; dir < 4; dir ++){
						var direction = getDir(dir);
						var pos = {x: x + direction.x, y: y + direction.y};

						//边界判断
						if(pos.x < 0 || pos.x >= 4 || pos.y < 0 || pos.y >= 4) continue;

						var tmpTile = listTile[pos.x][pos.y];

						if(tmpTile && tmpTile.style.text == tile.style.text) return true;
					}
				}
			}
		}

		return false;
	}

	/* 键盘监听 */
	function listenKey(){
	  var map = {
	    38: 0, // 上
	    39: 1, // 右
	    40: 2, // 下
	    37: 3, // 左
	    87: 0, // W
	    68: 1, // D
	    83: 2, // S
	    65: 3  // A
	  };

	  document.addEventListener('keydown', function (event) {
	    var mapped    = map[event.which];

	    if(mapped !== undefined){
	    	event.preventDefault();
	    	keyDeal('move', mapped);	    		
	    } 
	    if(event.which == 82) keyDeal('restart');
	  });	  	
	}

	/* 获取方向量 */
	function getDir(value){
	  var map = {
	    0: { x: -1,  y: 0 }, // 上
	    1: { x: 0,  y: 1 },  // 右
	    2: { x: 1,  y: 0 },  // 下
	    3: { x: 0, y: -1 }   // 左
	  };		

	  return map[value];
	}

	/*根据位置获取块*/
	function getTile(pos){
		if(pos.x < 0 || pos.x > 4 || pos.y < 0 || pos.y > 4){
			return null;
		}

		return listTile[pos.x][pos.y];
	}

	/* 键盘处理 */
	function keyDeal(event, value){
		if(event == 'move'){
			move(value)
		}else if(event == 'restart'){
			restart();
		}
	}

	/* 移动处理 */
	function move(dir){
		var isMoved = false;

		switch (dir) {
			case 0: //上
				for(var col = 0; col < 4; col ++ ){

					//往前推
					for(var row = 0; row < 4; row ++){
						if(listTile[row][col]) continue;
						for(var tmp = row + 1; tmp < 4; tmp ++){
							if(listTile[tmp][col]){
								moveTile(listTile[tmp][col], {x:row, y: col})
								listTile[row][col] = listTile[tmp][col];
								listTile[tmp][col] = null;
								isMoved = true;
								break;
							}
						}
					}

					//合并
					for(var row = 0; row < 3; row ++){
						if(listTile[row][col] === null) break;
						if(listTile[row + 1][col] === null) break;

						//不相同
						if(listTile[row][col].style.text != listTile[row + 1][col].style.text) continue;

						//相同
						listTile[row][col].style.text *= 2;
						moveTile(listTile[row + 1][col], {x: row, y: col}, true);						
						isMoved = true;

						//向前推
						for(var tmp = row + 1; tmp < 4; tmp ++){
							if(listTile[tmp][col]){
								moveTile(listTile[tmp][col], {x:row, y: col})
								listTile[row][col] = listTile[tmp][col];
								listTile[tmp][col] = null;
								isMoved = true;
								break;
							}
						}						

						domScore.innerHTML = +domScore.innerHTML + +listTile[row][col].style.text;
					}
				}
				break;
			case 1: //右

				break;
			case 2: //下

				break;
			case 3: //左
				for(var row = 0; row < 4; row ++ ){

					//往前推
					for(var col = 0; col < 4; col ++){
						if(listTile[row][col]) continue;
						for(var tmp = col + 1; tmp < 4; tmp ++){
							if(listTile[row][tmp]){
								moveTile(listTile[row][tmp], {x:row, y: col})
								listTile[row][col] = listTile[row][tmp];
								listTile[row][tmp] = null;
								isMoved = true;
								break;
							}
						}
					}

					//合并
					for(var col = 0; col < 3; col ++){
						if(listTile[row][col] === null) break;
						if(listTile[row][col + 1] === null) break;

						//不相同
						if(listTile[row][col].style.text != listTile[row][col + 1].style.text) continue;

						//相同
						listTile[row][col].style.text *= 2;
						moveTile(listTile[row][col + 1], {x: row, y: col}, true);						
						isMoved = true;

						//向前推
						for(var tmp = col + 1; tmp < 4; tmp ++){
							if(listTile[row][tmp]){
								moveTile(listTile[row][tmp], {x:row, y: col})
								listTile[row][col] = listTile[row][tmp];
								listTile[row][tmp] = null;
								isMoved = true;
								break;
							}
						}						

						domScore.innerHTML = +domScore.innerHTML + +listTile[row][col].style.text;
					}
				}
				break;

				
		}
		if(isMoved){
			addRndTile();
			if(!isMoveAvailable) alert('游戏结束');
		}
	}

	/* 移动块（动画） */
	function moveTile(tile, pos, del){
		del = del || false;		
		var x =pos.y > 0 ? pos.y * 106 + 15 * pos.y : pos.y * 106,
			y =pos.x > 0 ? pos.x * 106 + 15 * pos.x : pos.x * 106;

			//这里对于动画的操作还不太了解，就通过setTimeOut来模拟动画结束之后的操作
			//发现不能直接操作style，所以只能操作position
			zr.animate(tile.id).when(300, {position:[x - tile.style.x, y - tile.style.y]}).start('SinusoidalInOut');
			//动画结束后，重置position			
			setTimeout(function(){
				zr.modShape(tile.id, {style:{x:x, y:y, color: Math.log2(+tile.style.text) >= 12 ? colors[0].back : colors[Math.log2(+tile.style.text)].back,textColor: Math.log2(+tile.style.text) >= 12 ? colors[0].back : colors[Math.log2(+tile.style.text)].color}, position: [0, 0]});
				if(del) {
					listTile[tile.cell.row][tile.cell.col] = null;
					zr.delShape(tile.id);
				}else{
					tile.cell.row = pos.x;
					tile.cell.col = pos.y;	
				}
				
			}, 400);				
	}

	/* 新游戏 */
	function restart(){
		zr.clear();
		genGrid();
		initListTile();
		genStartTile(2);
		domScore.innerHTML = '0';
	}

	(function(){
		listenKey();
		domRestart.addEventListener('click', restart);
		restart();		
	})();

});
